home *** CD-ROM | disk | FTP | other *** search
- name msxapc
- ; File MSXAPC.ASM
- ; Last modification: 20 April 1986
-
- ; System dependent module for NEC APC
- ; ************ START MSXAPC.ASM ***********************************
-
- ; Kermit system dependent module for NEC Advanced Personal Computer (APC)
- ; Ron Blanford, University of Washington, August 1984
-
- ; Added global entry point vstat for use by Status in mssset.
- ; Also trimmed off trailing commas in publics. Joe R. Doupnik 12 March 1986
- ; Add global procedures ihosts and ihostr to handle host initialization
- ; when packets are to be sent or received by us,resp. 24 March 1986
- ; Add global procedure dtrlow (with discon in place of serhng) to force DTR
- ; and RTS low in response to Kermit command Hangup. [jrd]
- ; Add global procedure Dumpscr, called by Ter in file msster, to dump screen
- ; to a file. Just does a beep for now. 13 April 1986 [jrd]
- ; Include modifications by Ron Blanford to Dobaud and Getbaud. 14 April 1986
- ; In proc Outchr add override of xon from chkxon sending routine.
- ; This makes a hand typed Xoff supress the xon flow control character sent
- ; automatically as the receiver buffer empties. 20 April 1986 [jrd]
- ;
- ;
- ; Modified to get key scan codes directly from fifo buffer in IO.SYS
- ; This version works with MS-DOS Versions 2.00 (000) and 2.11 (001); it
- ; should work with future MS-DOS revisions so long as NECIS maintains
- ; the configuration table in IO.SYS - the thing most apt to fail is the
- ; key autorepeat because kbrepflg is furthest from a hook in config table.
- ; If this happens the equate for offset of kbrepflg will need adjusting.
- ; Ian Gibbons, University of Hawaii, 10/26/84
-
- ; Fixed incorrect timer command port assignment so that program will run
- ; under MS-DOS 2.00 as well as 2.11.
- ; Added autodetermination of color/mono using crttype byte in IO.SYS; this
- ; works only under DOS 2.11 (and future above ?)
- ; IG 10/28/84
- ; Added direct CRT I/O handling through BIOS in order to increase speed and
- ; flexibility of help menus. It gives only an imitation window but it works
- ; fairly well.
- ; IG 10/31/84
- ; Added simplified mode line data to the [Connecting to host...]" line which
- ; has been moved here from MSTERM in order to have more system dependent
- ; control.
- ; IG 11/4/84
- ; Make unredefined break/stop key act as a scroll/noscroll key in telnet by
- ; sending alternately a ^S and a ^Q.
- ; IG 11/5/84
- ; By now code for this MSXAPC module could well be divided into separate
- ; transmission and terminal modules, but I don't want to spend more time
- ; on it. It's not as readable as it might be, but so far as I know
- ; everything works.IG 11/6/84
-
- public serini, serrst, clrbuf, outchr, coms, vts, vtstat, dodel
- public ctlu, cmblnk, locate, lclini, lclrst, prtchr, dobaud
- public discon, clearl, dodisk, getbaud, beep
- public count, xofsnt, puthlp, putmod, clrmod, poscur
- public sendbr, term, machnam, setktab, setkhlp, showkey
- public ihosts, ihostr, dtrlow, dumpscr ; [jrd]
- include mssdef.h
-
- false equ 0
- true equ 1
-
- BIOS EQU 0DCH ; NEC-APC BIOS interrupt call
- fifoclr equ 6 ; clears keyboard fifo buffer
- crtcmd equ 7 ; Direct CRT I/O command call
-
- ; port assignments for 8251 serial controllers
-
- ; Standard interface
-
- mndata equ 30H ; Data port (read/write)
- mnst1a equ 32H ; Status port (when read)
- mncmda equ 32H ; Command port (when written)
- mnst2a equ 34H ; Alternate status port (when read)
- mnmska equ 34H ; Mask port (when written)
- mntdca equ 36H ; Transmit disable port (write only)
-
- ; Optional (H14) interface
-
- mndatb equ 31H ; Data port (read/write)
- mnst1b equ 33H ; Status port (when read)
- mncmdb equ 33H ; Command port (when written)
- mnst2b equ 35H ; Alternate status port (when read)
- mnmskb equ 35H ; Mask port (when written)
- mntdcb equ 37H ; Transmit disable port (write only)
-
- ; Status bits from mnst1
-
- txrdy equ 01H ; Bit for output ready.
- rxrdy equ 02H ; Bit for input ready.
-
- ; Command values for mncmd
-
- ccmd equ 37H ; RTS & DTR high, RX & TX enabled, reset ERR
- cbrk equ 08H ; break enabled
- cmode equ 40H ; enable mode reset
- mmode equ 4EH ; 16x rate, 8 data, no parity, 1 stop
-
- ; Mask values for mnmsk
-
- txmsk equ 01H ; disables transmit ready interrupt
- rxmsk equ 02H ; disables receive ready interrupt
- tbemsk equ 04H ; disables transmit buffer empty interrupt
-
-
- ; port assignments for 8253 timers
-
- ; Standard interface
-
- tmdata equ 2BH ; data port
- tmcmda equ 2FH ; command port (Was 27H Ian 10/27/84)
-
- ; Optional (H14) interface
-
- tmdatb equ 61H ; data port
- tmcmdb equ 67H ; command port
-
- ; values for tmcmd which select timer channel and mode
-
- tmsela equ 76H ; Channel 1, mode 3 (standard port)
- tmselb equ 36H ; Channel 0, mode 3 (optional port)
-
- ; Timer information for current port selection
-
- tmrinfo struc
- tmdat dw 0 ; data port
- tmcmd dw 0 ; command port
- tmsel db 0 ; byte which selects channel and mode
- tmrinfo ends
-
-
- ; port assignments for 8259 interrupt controllers
-
- ; Standard interface
-
- intcmda equ 20H ; Command port (master controller)
- intmska equ 22H ; Mask port
- ictmsk equ 08H ; Timer interrupt mask (to master)
- icsmska equ 02H ; Standard serial interrupt mask (to master)
- icsvcta equ 11H ; Interrupt vector for standard interface
-
- ; Optional (H14) interface
-
- ; The interrupt request vector for the optional (H14) serial interface is
- ; jumper-selectable to any of vectors IR2, IR5, IR8, or IR12. NEC recommends
- ; that IR8 be used, so that has been selected as the default here. To use
- ; any of the other vectors, set the following conditionals appropriately.
- ; Only one of the following should be true:
-
- IR2 equ false ; interrupt vector 2
- IR5 equ false ; interrupt vector 5
- IR8 equ true ; interrupt vector 8
- IR12 equ false ; interrupt vector 12
-
- IF IR2
- intcmdb equ 20H ; Command port (master controller)
- intmskb equ 22H ; Mask port
- icsmskb equ 04H ; Interrupt mask
- icsvctb equ 12H ; Interrupt table index
- ENDIF
-
- IF IR5
- intcmdb equ 20H ; Command port (master controller)
- intmskb equ 22H ; Mask port
- icsmskb equ 20H ; Interrupt mask
- icsvctb equ 15H ; Interrupt table index
- ENDIF
-
- IF IR8
- intcmdb equ 28H ; Command port (slave controller)
- intmskb equ 2AH ; Mask port
- icsmskb equ 02H ; Interrupt mask
- icsvctb equ 19H ; Interrupt table index
- ENDIF
-
- IF IR12
- intcmdb equ 28H ; Command port (slave controller)
- intmskb equ 2AH ; Mask port
- icsmskb equ 20H ; Interrupt mask
- icsvctb equ 1DH ; Interrupt table index
- ENDIF
-
- crtinfo struc ; Structure for color/mono formatting info
- nrmseq db esc,'[0m$' ; Default
- invseq db esc,'[7m$000' ; Inverse (extra space for color)
- bldseq db esc,'[17m$' ; Bold video
- nrmcrt dw 8080H ; Normal data for direct crt i/o
- bldcrt dw 9090H ; Inverse data for direct crt i/o
-
- crtinfo ends
-
-
- icEOI equ 20H ; generic end of interrupt for intcmd
- kbfifosiz equ 64 ; size of fifo buffer in IO.SYS
-
-
- ; miscellaneous constants
-
- ctrlP equ 10H ; ^P.
- ctrl_q equ 11H ; ^Q
- ctrl_s equ 13H ; ^S
- printkey equ 00FFH ; Scan code of unshifted PRINT key.
- brkstp equ 0096H ; Scan code of unshifted break/stop key.
- mntrgh equ bufsiz*3/4 ; High XON/XOFF trigger = 3/4 of buffer full.
-
- ; external variables used:
- ; drives - # of disk drives on system
- ; flags - global flags as per flginfo structure defined in pcdefs
- ; trans - global transmission parameters, trinfo struct defined in pcdefs
- ; portval - pointer to current portinfo structure (currently either port1
- ; or port2)
- ; port1, port2 - portinfo structures for the corresponding ports
-
- ; global variables defined in this module:
- ; xofsnt, xofrcv - tell whether we saw or sent an xoff.
-
- datas segment public 'datas'
- extrn drives:byte,flags:byte, trans:byte
- extrn portval:word, port1:byte, port2:byte, dmpname:byte ; [jrd]
-
- machnam db 'NEC APC$'
- nyimsg db cr,lf,'Not implemented$'
- badbd db cr,lf,'Unimplemented baud rate$'
- bdkscn db cr,lf,'Unable to install key translate table'
- db cr,lf,'Possibly incompatible MS-DOS version',cr,lf
- db cr,lf,'(MS-KERMIT can be used without keyboard translation'
- db ' feature)',cr,lf,'$'
- nokbtr db cr,lf,'No key translation table is installed$'
- hngmsg db cr,lf,' The phone should have hungup.',cr,lf,'$' ; [jrd]
- hnghlp db cr,lf,' The modem control lines DTR and RTS for the current'
- db ' port are forced low (off)'
- db cr,lf,' to hangup the phone. Normally, Kermit leaves them'
- db ' high (on) when it exits.'
- db cr,lf,'$' ; [jrd]
- rdbuf db 80 dup (?) ; temp buf [jrd]
- prtmsg db cr,lf,'You cannot redefine the PRINT key$'
- escmsg db cr,lf,'You cannot redefine the current CTRL-ESCAPE key$'
- hngcfm db cr,lf,'Please confirm DISCONNECT command. (Y/N) $'
- dismsg db cr,lf,'Disconnecting for 3 seconds',cr,lf,'$'
- rcnmsg db cr,lf,'Reconnected',cr,lf,'$'
- cnmsg db cr,lf,'Connecting to host at '
- cnmsgb db ' '
- db ' baud on port '
- cnmsgp db ' ',cr,lf,'(Type $'
- cnmsg1 db ' C to return to PC)',cr,lf,lf,lf,'$'
- crlf db cr,lf,'$'
- delstr db BS,BS,' ',BS,'$' ; Delete string.
- clrlin db cr,'$' ; Clear line (just the cr part).
- ceolseq db esc,'[K$' ; Clear to end of line
- cpseq db esc,'=rc' ; rc replaced by row and column before display
- clrseq db 01EH,01AH,'$' ; Home cursor and clear screen
- lstpos dw 0 ; column position for printer echoing
-
- ; Storage for color and mono formatting strings
-
- nrmcol db esc,'[0m$'
- invcol db esc,'[3;21m$' ; Yellow with green overline
- bldcol db esc,'[21m$' ; Yellow
- ncrtcol dw 8080H ; Green
- bcrtcol dw 0A0A0H ; Yellow
-
- ;nrmmon db esc,'[0m$'
- ;invmon db esc,'[7m$000' ; Inverse video
- ;bldmon db esc,'[17m$' ; Bold video
- ;ncrtmon dw 8080H ; Normal green
- ;bcrtmon dw 9090H ; Inverse video
-
- formdat crtinfo <>
- formdtl db $-formdat
-
- nocur db esc,'[>5h$' ; Disable cursor
- recur db esc,'[>5l$' ; Reenable cursor
- storcur db esc,'[s$' ; Store cursor position
- rstcur db esc,'[u$' ; Restore cursor position
- upcur db esc,'[A$' ; Move cursor up one line
- savcur dw 0 ; storage for cursor position
- msglns db 0 ; No of lines in help message
- rnoc dw 0 ; Raw NOC for screen write
-
- ; Data area for direct CRT I/O
-
- EVEN ; Force alignment to word boundary
- dispadr db 2000 dup (0) ; Storage for string data
- attradr db 2000 dup (0) ; Storage for attribute data
-
- ; Command block for direct CRT I/O
-
- cmd db 0 ; CRT command number
- la db 0 ; Line address (0-24 binary)
- ca db 0 ; Column address (0-79 binary)
- noc dw 0 ; Number of chars (0-2000 binary)
- dispptr dw dispadr ; Pointer to string data block
- dispseg dw datas ;
- attrptr dw attradr ; Pointer to attribute data block
- attrseg dw datas
-
- ourarg termarg <>
- modem mdminfo <mndata,mnst1a,mncmda,0,0,0,0>
- timer tmrinfo <tmdata,tmcmda,tmsela>
-
- ourflgs db 0 ; Flags for telnet options
- fprint equ 80H ; echo screen output to printer
- movcur equ 40H ; cursor moved - needs resetting
- kbtrflg equ 20H ; local flag showing if kb trans.is enabled
- autorepflg equ 10H ; is this an autorepeat cycle
- inited equ 8H ; are we initiating first call to term
- tlnxof equ 4H ; have we sent a ^S in telnet with brk/stp
- savscn dw 0 ; save last key-in for auto repeat if needed
- escscan dw 0 ; scan code for current ctrl-escape key
-
- oldsera dw ? ; old serial handler for standard port
- oldsega dw ? ; segment of above
- oldmska db ? ; old interrupt controller mask
- portina db 0 ; Has comm port been initialized.
-
- oldserb dw ? ; old serial handler for optional port
- oldsegb dw ? ; segment of same.
- oldmskb db ? ; old interrupt controller mask
- portinb db 0 ; Has comm port been initialized.
-
- dosseg dw 40H ; Segment to read IO.SYS
- zero dw 0 ; Use to load segment regs for low core
-
- ; Space for addresses in IO.SYS to be calculated at run time in 'lclini'
-
- configptr equ 3H ; Offset of pointer to base of config table
- configbas dw 0 ; base address of config table in IO.SYS
- fifobas dw 0 ; equ 0A62H for DOS 2.11
-
- ; offsets from configbas
- statlnptr equ 0CH
- kbinptr equ 2CH ; kbin addr = base of fifodata area (fifobas)
- crtptr equ 48H
-
- ; offsets from fifobas
- kbin equ 0 ; fifobas
- kbout equ 1 ; fifobas + 1
- kbfifo equ 2 ; fifobas + 2
- sfkeyflg equ 043H ; fifobas + 043H
- kbrepflg equ 0D9H ; fifobas + 0D9H
-
- xofsnt db 0 ; Say if we sent an XOFF.
- xofrcv db 0 ; Say if we received an XOFF.
-
- ; variables for serial interrupt handler
- source db bufsiz DUP (?) ; Buffer for data from port.
- srcpnt dw 0 ; Pointer in buffer (DI).
- count dw 0 ; Number of chars in int buffer.
- savesi dw 0 ; Save SI register here.
- dw 80 DUP (?) ; local stack for interrupt processing
- mnstk dw ?
- mnsp dw ? ; remote stack info
- mnsseg dw ?
-
- shkbuf db 300 dup (?) ; room to display key definition
- shkmsg db ' Scan code: '
- shkmln equ $-shkmsg
- shkms1 db cr,lf,' Definition: '
- shkm1ln equ $-shkms1
-
- setktab db 24
- mkeyw 'BACKSPACE',9CH
- mkeyw 'F1',80H
- mkeyw 'F2',81H
- mkeyw 'F3',82H
- mkeyw 'F4',83H
- mkeyw 'F5',84H
- mkeyw 'F6',85H
- mkeyw 'F7',86H
- mkeyw 'F8',87H
- mkeyw 'F9',88H
- mkeyw 'F10',89H
- mkeyw 'F11',8AH
- mkeyw 'F12',8BH
- mkeyw 'F13',8CH
- mkeyw 'F14',8DH
- mkeyw 'F15',8EH
- mkeyw 'F16',8FH
- mkeyw 'F17',90H
- mkeyw 'F18',91H
- mkeyw 'F19',92H
- mkeyw 'F20',93H
- mkeyw 'F21',94H
- mkeyw 'F22',95H
- mkeyw 'SCAN',-1
-
- setkhlp db cr,lf,'Either keyname: Backspace, F1, ...,F22',cr,lf
- db ' or "SCAN" followed by scan code'
- db ' (given by SHOW KEY)',cr,lf,'$'
-
- comptab db 7
- mkeyw '1',1
- mkeyw '2',0
- mkeyw 'COM1',1
- mkeyw 'COM2',0
- mkeyw 'H14',0
- mkeyw 'OPTIONAL',0
- mkeyw 'STANDARD',1
-
- bddat label word
- dw 0D30H ; 45.5 baud
- dw 0C00H ; 50 baud
- dw 0800H ; 75 baud
- dw 0574H ; 110 baud
- dw 0476H ; 134.5 baud
- dw 0400H ; 150 baud
- dw 0200H ; 300 baud
- dw 0100H ; 600 baud
- dw 0080H ; 1200 baud
- dw 0055H ; 1800 baud
- dw 004DH ; 2000 baud
- dw 0040H ; 2400 baud
- dw 0020H ; 4800 baud
- dw 0010H ; 9600 baud
- dw 0008H ; 19200 baud
- dw 0004H ; 38400 baud (not tested - may not work)
-
- ; some static data for mode line
-
- unkbaud db ' Unk ' ; must be 5 chars...
- baudn db ' 45.5' ; [g4 start]
- db ' 50 '
- db ' 75 '
- db ' 110 '
- db ' 135 '
- db ' 150 '
- db ' 300 '
- db ' 600 '
- db ' 1200'
- db ' 1800'
- db ' 2000'
- db ' 2400'
- db ' 4800'
- db ' 9600'
- db '19200' ; [g4 end]
- baudnsiz equ 15 ; # of baud rates known (tbl size / 5)
-
- datas ends
-
-
- code segment public 'code'
- extrn comnd:near, dopar:near, escprt:near
- extrn sleep:near ; [jrd]
- assume cs:code,ds:datas
-
- ; local initialization routine, called by Kermit initialization.
-
- LCLINI PROC NEAR
- cld
- mov flags.vtflg,0 ; turn off heath emulation
- push es
- mov es,dosseg
- mov bx,configptr
- mov bx,es:[bx] ; Get offset of configuration table in IO.SYS
- mov configbas,bx ; store it
- mov cl,fifoclr ; Clear fifobuffer in case user has been
- int bios ; typing while program was loading
- mov bx,es:[bx].kbinptr ; Should be address of kbin
- mov cl,es:[bx] ; Confirm we're in right location
- cmp cl,byte ptr es:1[bx] ; by showing kbin = kbout
- jne lclin1 ; Fails for DOS 2.00 (no kbinptr)
- mov fifobas,bx ; Kbin is base of fifo area
- or ourflgs,kbtrflg ; Show we have a key tranlate table
- jmp short lclin2 ; Localization finished
- lclin1: mov bx,configbas ; DOS 2.00 does have pointer to status line
- mov bx,es:[bx].statlnptr ; Address of 'MS-DOS' in status line
- sub bx,6BH ; Work back to where kbin should be
- mov cl,es:[bx] ; Confirm we're in right location
- cmp cl,byte ptr es:1[bx] ; by showing kbin = kbout
- jnz lclin3 ; Nothing else to try - report failure
- mov fifobas,bx ; We've made it!
- or ourflgs,kbtrflg ; Show we have a key tranlate table
- xor ax,ax ; Set zero flag for mono format default
- jmp short lcli20
- lclin2: mov bx,configbas
- mov bx,es:[bx].crtptr ; Get address of crttype byte
- mov al,es:[bx] ; get the crttype byte
- test al,1 ; Is it a color crt?
- lcli20: mov dx,ds ; DOS 2.00 has no crt data and
- mov es,dx ; and defaults to mono
- mov cl,formdtl ; Length of crt format block
- mov di,offset formdat ; Where we want data
- jnz lcli21 ; No, it's color
- jmp short lclin4
- lcli21: mov si,offset nrmcol ; Source of color data
- rep movsb ; Move data to working location
- jmp short lclin4
- lclin3: mov dx,offset bdkscn
- call tmsg
- and ourflgs,not kbtrflg ; Show no translate table enabled
- lclin4: mov dx,offset formdat.nrmseq ; set to our normal background color
- call tmsg
- pop es
- ret
- LCLINI ENDP
-
- ; Local reset routine, called upon exit from Kermit
-
- LCLRST PROC NEAR
- ret
- LCLRST ENDP
-
- ; this is called by Kermit initialization. It checks the
- ; number of disks on the system, sets the drives variable
- ; appropriately. The only problem is that a value of two
- ; is returned for single drive systems to be consistent
- ; with the idea of the system having logical drives A and
- ; B. Returns normally.
-
- DODISK PROC NEAR
- mov ah,gcurdsk ; current disk value to AL.
- int dos
- mov dl,al ; put current disk in DL.
- mov ah,seldsk ; select current disk.
- int dos ; get number of drives in AL.
- mov drives,al
- ret
- DODISK ENDP
-
- ; show the definition of a key. The terminal argument block (which contains
- ; the address and length of the definition tables) is passed in ax.
- ; Returns a string to print in AX, length of same in CX.
- ; Returns normally.
-
- ; In this version, the complete untranslated key scan codes are obtained
- ; from the fifo buffer in IO.SYS. The fifo buffer pointers are then updated
- ; to show that the key has been read. Certain key scan codes which are
- ; intercepted in the kb interrupt routine give a blank or functional response
- ; to SHOW KEY (eg FNC + CTRL + BREAK-STOP, PRINT, and CTRL + 0...9 )
- ; and these cannot be translated.
-
- SHOWKEY PROC NEAR
- push es
- test ourflgs,kbtrflg
- jnz showk0
- push ax ; Keep stack balanced
- mov bx,ax
- and [bx].flgs,not havtt ; reset flag
- mov dx,offset nokbtr ; Inform no table installed and return
- jmp short shoerr
-
- showk0: push ax ; save the terminal argument block
- mov al,trans.escchr ; calculate scan code for ctrl-escape key
- add al,40H ; uncontrolify escape char
- mov ah,2 ; control byte
- mov escscan,ax ; save it
- showk1: call inscan ; get key-in scan code from IO.SYS
- jmp short showk1 ; Nothing there yet - keep trying
- nop
- call inckbo ; increment kbout pointer
- cmp al,printkey ; Is it the print key (any version) ?
- jnz show11
- mov dx,offset prtmsg ; If so complain
- jmp short shoerr
- show11: cmp al,byte ptr escscan ; Is it current ctrl-escape key ?
- jnz show12
- test ah,02 ; With ctrl + anything
- jz show12
- mov dx,offset escmsg ; Then complain
- jmp short shoerr
- show12: cld
- mov cx,ds
- mov es,cx
- push ax ; save scan code
- mov di,offset shkbuf ; move 'Scan code' message to buffer
- mov si,offset shkmsg
- mov cx,shkmln
- rep movsb
- call nout ; add scan code to buffer
- mov si,offset shkms1 ; move 'Definition' message to buffer
- mov cx,shkm1ln
- rep movsb
- pop ax ; retrieve scan code
- pop bx ; and terminal argument block
- mov cx,[bx].klen ; length of translation table
- jcxz showk3 ; no table, key not defined
- push di
- mov di,[bx].ktab ; get table address
- repne scasw ; look for scan code
- mov si,di
- pop di
- jne showk3 ; not defined
- sub si,[bx].ktab ; compute entry offset in table
- sub si,2
- add si,[bx].krpl ; index to replacement
- mov si,[si] ; get its address
- mov cl,[si] ; get its length
- mov ch,0
- inc si
- rep movsb ; transfer replacement to display buffer
- showk3: mov ax,offset shkbuf ; return address of buffer in ax
- mov cx,di ; and length in cx
- sub cx,ax
- pop es
- ret
- shoerr: call tmsg
- mov cx,0 ;
- pop ax ; get rid of junk
- pop es
- ret
- SHOWKEY ENDP
-
- ; copy numeric value from AX to ASCII buffer indicated by DI. DI is updated.
-
- NOUT PROC NEAR
- mov dx,0 ; zero high word
- mov bx,10 ; divide
- div bx
- push dx ; save remainder digit
- or ax,ax ; anything left?
- jz nout1 ; no, start output phase
- call nout
- nout1: pop ax ; retrieve a digit
- add al,'0' ; make it ASCII
- stosb ; put it in buffer
- ret
- NOUT ENDP
-
- ; skip returns if no character available at port,
- ; otherwise returns with char in al, # of chars in buffer in dx.
-
- PRTCHR PROC NEAR
- call chkxon ; see if we have to xon the host.
- cmp count,0
- jnz prtch2
- jmp rskp ; No data - check console.
- prtch2: pushf ; save current interrupt value
- cli ; disable interrupts while manipulating pointers
- mov si,savesi
- lodsb ; get a byte
- cmp si,offset source + bufsiz ; bigger than buffer?
- jb prtch1 ; no, keep going
- mov si,offset source ; yes, wrap around
- prtch1: dec count
- mov savesi,si
- mov dx,count ; return # of chars in buffer
- popf ; restore original interrupt flag
- ret
- PRTCHR ENDP
-
- ; local routine to see if we have to transmit an xon
-
- CHKXON PROC NEAR
- push bx
- mov bx,portval
- cmp [bx].floflg,0 ; doing flow control?
- je chkxo1 ; no, skip all this
- cmp xofsnt,false ; have we sent an xoff?
- je chkxo1 ; no, forget it
- cmp count,mntrgh ; below trigger?
- jae chkxo1 ; no, forget it
- mov ax,[bx].flowc ; ah gets xon
- call outchr ; send it
- nop ; ignore failure
- nop
- nop
- mov xofsnt,false ; remember we've sent an xon.
- chkxo1: pop bx ; restore register
- ret ; and return
- CHKXON ENDP
-
- ; Put the char in AH to the serial port. This assumes the
- ; port has been initialized. Should honor xon/xoff. Skip returns on
- ; success, returns normally if the character cannot be written.
-
- OUTCHR PROC NEAR
- mov bp,portval
- cmp ds:[bp].floflg,0 ; Are we doing flow control.
- je outch2 ; No, just continue.
- sub cx,cx ; clear counter
- cmp ah,byte ptr [bp].flowc ; sending xoff? [jrd]
- jne outch1 ; ne = no
- mov xofsnt,false ; supress xon from chkxon buffer routine
- outch1: cmp xofrcv,true ; Are we being held?
- jne outch2 ; No - it's OK to go on.
- loop outch1 ; held, try for a while
- mov xofrcv,false ; timed out, force it off and fall thru.
- outch2: push dx ; Save register.
- sub cx,cx
- mov al,ah ; Parity routine works on AL.
- call dopar ; Set parity appropriately.
- mov ah,al ; Don't overwrite character with status.
- mov dx,modem.mdstat ; port status register
- outch3: in al,dx
- test al,txrdy ; Transmitter ready?
- jnz outch4 ; Yes
- loop outch3
- jmp outch5 ; Timeout
- outch4: mov al,ah ; Now send it out
- mov dx,modem.mddat
- out dx,al
- pop dx
- jmp rskp
- outch5: pop dx
- ret
- OUTCHR ENDP
-
- ; IHOSTS - Initialize the host by sending XON, or equivalent, and enter the
- ; cycle of clear input buffer, wait 1 second, test if buffer empty then exit
- ; else repeat cycle. Requires that the port be initialized before hand.
- ; Ihosts is used by the local send-file routine just after initializing
- ; the serial port.
- ; 22 March 1986 [jrd]
-
- IHOSTS PROC NEAR
- push ax ; save the registers
- push bx
- push cx
- push dx
- mov bx,portval ; port indicator
- mov ax,[bx].flowc ; put Go-ahead flow control char in ah
- call outchr ; send it (release Host's output queue)
- nop ; outchr can do skip return
- nop
- nop
- ihosts1:call clrbuf ; clear out interrupt buffer
- mov ax,1 ; sleep for 1 second
- call sleep ; procedure sleep is in msscom.asm
- call prtchr ; check for char at port
- jmp ihosts1 ; have a char in al, repeat wait/read cycle
- nop ; prtchr does skip return on empty buffer
- pop dx ; empty buffer. we are done here.
- pop cx
- pop bx
- pop ax
- ret
- IHOSTS ENDP
-
- ; IHOSTR - initialize the remote host for our reception of a file by
- ; sending the flow-on character (XON typically) to release any held
- ; data. Called by receive-file code just after initializing the serial
- ; port. 22 March 1986 [jrd]
- IHOSTR PROC NEAR
- push ax ; save regs
- push bx
- push cx
- mov bx,portval ; port indicator
- mov ax,[bx].flowc ; put Go-ahead flow control char in ah
- call outchr ; send it (release Host's output queue)
- nop ; outchr can do skip return
- nop
- nop
- pop cx
- pop bx
- pop ax
- ret
- IHOSTR ENDP
-
- DTRLOW PROC NEAR ; Global proc to Hangup the Phone by making
- ; DTR and RTS low.
- mov ah,cmtxt ; allow text to be able to display help
- mov bx,offset rdbuf ; dummy buffer
- mov dx,offset hnghlp ; help message
- call comnd ; get a confirm
- jmp r
- call discon ; try using preexisting routine
- ; [jrd] call serhng ; drop DTR and RTS
- ; [jrd] mov ah,prstr ; give a nice message
- ; [jrd] mov dx,offset hngmsg
- ; [jrd] int dos
- jmp rskp
- DTRLOW ENDP
-
- ; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low
- ; to terminate the connection. 29 March 1986 [jrd]
- ; Calling this twice without intervening calls to serini should be harmless.
- ; Returns normally.
- ; SERHNG is Not Yet Implemented. Use existing procedure discon below.
-
-
-
- ; Send a break out the current serial port. Returns normally.
-
- SENDBR PROC NEAR
- mov dx,modem.mdcom ; send to command port
- mov al,cbrk+ccmd ; add break to normal command
- out dx,al
- sub cx,cx ; wait a while
- sndbr1: loop sndbr1
- mov al,ccmd ; restore normal command
- out dx,al
- ret ; and return.
- SENDBR ENDP
-
- DISCON PROC NEAR
- mov dx,offset hngcfm
- call besure ; Get confimation of command
- jmp short discn1
- nop
- mov dx,offset dismsg ; Say what we're doing
- call tmsg
- mov al,CCMD
- xor al,2 ; Reset bit to drop DTR.
- mov dx,modem.mdcom
- out dx,al
- mov bx,05H ; Set outer counter 5 X --> 3sec.
- pause2: xor cx,cx
- pause3: push bx ; Waste time for 600ms.
- pop bx
- loop pause3 ; Loop on inner loop.
- dec bx
- jnz pause2 ; Loop on outer loop.
- or al,2 ; Set bit to enable DTR again.
- out dx,al
- mov dx,offset rcnmsg
- call tmsg
- discn1: ret
- DISCON ENDP
-
- BESURE PROC NEAR ; Receives addr of prompt in DX.
- call tmsg
- mov ah,conin
- int dos
- and al,137Q ; Convert to upper case if necessary.
- cmp al,'Y'
- jz besur1 ; We must return rskp for a 'Y'/'y'
- mov dx,offset crlf ; For any other character input send a cr/lf.
- call tmsg
- ret ; And return.
- besur1: jmp rskp
- BESURE ENDP
-
-
- ; Clear the input buffer. This throws away all the characters in the
- ; serial interrupt buffer. This is particularly important when
- ; talking to servers, since NAKs can accumulate in the buffer.
- ; Returns normally.
-
- CLRBUF PROC NEAR
- pushf ; save current interrupt value
- cli ; disable interrupts
- mov ax,offset source ; reset pointers to beginning of buffer
- mov srcpnt,ax
- mov savesi,ax
- mov count,0
- popf ; restore original interrupt value
- ret
- CLRBUF ENDP
-
- ; Set the baud rate for the current port, based on the value in the
- ; portinfo structure. On entry, previous value of baud rate is saved in AX.
- ; Returns normally.
-
- DOBAUD PROC NEAR
- push ax ; save regs. [jrd]
- push bx
- push dx
- push bp
- mov bp,portval
- mov bx,ds:[bp].baud ;make sure new value is valid
- cmp bx,BAUDSIZ ; [RB] don't get stuck at 1200 baud
- jae dobd0 ; [RB]
- shl bx,1
- add bx,offset bddat
- cmp word ptr [bx],0FFH
- jne dobd1 ; [RB]
- dobd0: mov ds:[bp].baud,ax ; [RB] replace bad rate with previous value
- mov dx,offset badbd
- jmp tmsg
- dobd1: mov dx,timer.tmcmd ; [RB] timer command port
- mov al,timer.tmsel ;select proper channel and mode
- out dx,al
- mov ax,[bx] ;get timer initializer for this rate
- mov dx,timer.tmdat ;timer data port
- out dx,al ;output low byte
- mov al,ah
- out dx,al ;output high byte
- pop bp ; [jrd]
- pop dx
- pop bx
- pop ax
- ret
- DOBAUD ENDP
-
- ; Get the current baud rate from the serial card and set it
- ; in the portinfo structure for the current port. Returns normally.
- ; This is called any time the baud rate is to be displayed.
-
- ; We can't determine the baud rate on the APC, so just set it
- ; to the default of 1200 if the value is currently illegal.
-
- GETBAUD PROC NEAR
- push bx ; [jrd]
- push bp ; Additions by Ron Blanford 14 April 1986
- mov bp,portval
- mov bx,ds:[bp].baud
- cmp bx,BAUDSIZ
- jae getbd2
- shl bx,1
- add bx,offset bddat
- cmp word ptr [bx],0FFh
- jne getbd3
- getbd2: mov ds:[bp].baud,B1200
- getbd3: pop bp
- pop bx ; [jrd]
- ret
- GETBAUD ENDP
-
- ; Set the mode for the current port. This is part of the serial
- ; initialization routine.
-
- DOMODE PROC NEAR
- mov dx,modem.mdcom ;send 3 zeros to command port to reset chip
- mov al,0
- out dx,al
- mov al,0
- out dx,al
- mov al,0
- out dx,al
- mov al,cmode ;enable mode setting
- out dx,al
- push ax ;allow 8251 time to reset
- pop ax
- push ax
- pop ax
- mov al,mmode ;mode: 16x rate, 8 data, no parity, 1 stop
- out dx,al
- mov al,ccmd ;RTS & DTR high, RX & TX enabled, reset errors
- out dx,al
- ret
- DOMODE ENDP
-
- ; Reassure user about connection to the host. Tell him what escape
- ; sequence to use to return and the communications port and baud
- ; rate being used. [19b]
-
- DOMSG PROC NEAR
- push ax ; save regs. [jrd]
- push bx
- push cx
- push si
- mov bx,offset ourarg ; get argument block
- mov al,[bx].baudb ; get baud bits
- mov si,offset unkbaud ; Assume unknown baud.
- cmp al,baudnsiz ; too big?
- jnb dmsg12 ; yes, use default
- mov cl,2 ; each is 5 bytes long
- shl al,cl ; 4 X
- add al,[bx].baudb ; make 4+1 = 5
- mov ah,0
- add ax,offset baudn
- mov si,ax
- dmsg12: mov cx,5 ; length of baud space
- mov di,offset cnmsgb
- rep movsb ; copy in baud rate
- mov al,'1'
- cmp ourarg.prt,1 ; One means port 1
- je dmsg15 ; yes, keep going
- mov al,'2' ; Zero means port 2
- dmsg15: mov cnmsgp,al ; fill in port number
- mov dx,offset cnmsg
- call tmsg
- call escprt ; in MSSET
- mov dx,offset cnmsg1
- call tmsg
- pop si ; [jrd]
- pop cx
- pop bx
- pop ax
- ret
- DOMSG ENDP
-
- ; set the current port.
-
- COMS PROC NEAR
- mov dx,offset comptab ;get port selection
- mov bx,0
- mov ah,cmkey
- call comnd
- jmp r
- push bx
- mov ah,cmcfm ;get a confirmation
- call comnd
- jmp comx
- nop
- pop bx
- mov flags.comflg,bl ;save port selection
- cmp flags.comflg,1
- jne coms2
- mov ax,offset port1 ;set to run on port 1
- mov portval,ax
- call resetb ;reset port 2, if in use
- call inita ;set up port 1
- ret
- coms2: mov ax,offset port2 ;set to run on port 2
- mov portval,ax
- call reseta ;reset port 1, if in use
- call initb ;set up port 2
- ret
- comx: pop bx
- ret
- COMS ENDP
-
- ; initialization for using serial port. This routine performs
- ; any initialization necessary for using the serial port, including
- ; setting up interrupt routines, setting buffer pointers, etc.
- ; Doing this twice in a row should be harmless (this version checks
- ; a flag and returns if initialization has already been done).
- ; SERRST below should restore any interrupt vectors that this changes.
- ; Returns normally.
-
- SERINI PROC NEAR
- cmp flags.comflg,1
- jne seri2
- call resetb
- call inita
- ret
- seri2: call reseta
- call initb
- ret
- SERINI ENDP
-
- ; Reset the serial port. This is the opposite of serini. Calling
- ; this twice without intervening calls to serini should be harmless.
- ; Returns normally.
-
- SERRST PROC NEAR
- call reseta ;reset port 1
- call resetb ;reset port 2
- mov dx,offset recur ; Reenable cursor display
- call tmsg
- and ourflgs,not inited ; Reset init flag for term usage
- ret
- SERRST ENDP
-
- ; Local routine to initialize the standard serial port
-
- INITA PROC NEAR
- cmp portina,1 ; Did we initialize port already? [21c]
- je inita0 ; Yes, so just leave. [21c]
- push es
- cli ; Disable interrupts
- mov ax,offset port1
- mov portval,ax
- xor ax,ax ; Address low memory
- mov es,ax
- mov ax,es:[4*icsvcta] ; save standard port interrupt vector
- mov oldsera,ax
- mov ax,es:[4*icsvcta+2]
- mov oldsega,ax
- mov ax,offset serint ; point to our routine
- mov es:[4*icsvcta],ax ; point at our serial routine
- mov es:[4*icsvcta+2],cs ; our segment
- mov dx,intmska ; set up standard port...
- in al,dx
- mov oldmska,al ; save old master controller mask
-
- ; NEC recommends that the timer interrupt be disabled during interrupt-
- ; driven serial I/O, but this disables the clock display and keyboard
- ; repeat. I have not had any problems leaving it enabled, so I will
- ; leave it alone here. If problems develop, uncomment the following
- ; line to disable timer interrupts. -- RonB
-
- ; or al,ictmsk ; disable timer interrupt
- and al,not icsmska ; enable serial interrupt at master controller
- out dx,al
- mov dx,mnmska ; enable serial interrupt at port
- mov al,txmsk+tbemsk ; disable tx and tbe interrupts (enable rx)
- out dx,al
- mov dx,mntdca ; enable operation of serial port
- mov al,0
- out dx,al
- mov modem.mddat,mndata
- mov modem.mdstat,mnst1a
- mov modem.mdcom,mncmda
- mov timer.tmdat,tmdata
- mov timer.tmcmd,tmcmda
- mov timer.tmsel,tmsela
- call domode
- call dobaud
- mov portina,1 ; Remember port has been initialized.
- call clrbuf ; Clear input buffer.
- sti ; Allow interrupts
- pop es
- inita0: ret
- INITA ENDP
-
- ; Local routine to initialize the optional (H14) serial port
-
- INITB PROC NEAR
- cmp portinb,1 ; Did we initialize port already? [21c]
- je initb0 ; Yes, so just leave. [21c]
- push es
- cli ; Disable interrupts
- mov ax,offset port2
- mov portval,ax
- xor ax,ax ; Address low memory
- mov es,ax
- mov ax,es:[4*icsvctb] ; save optional port interrupt vector
- mov oldserb,ax
- mov ax,es:[4*icsvctb+2]
- mov oldsegb,ax
- mov ax,offset serint ; point to our routine
- mov es:[4*icsvctb],ax ; point at our serial routine
- mov es:[4*icsvctb+2],cs ; our segment
- mov dx,intmskb ; set up optional port...
- in al,dx
- mov oldmskb,al ; save old master or slave controller mask
- and al,not icsmskb ; enable serial interrupt at controller
- out dx,al
- mov dx,mnmskb ; enable serial interrupt at port
- mov al,txmsk+tbemsk ; disable tx and tbe interrupts (enable rx)
- out dx,al
- mov dx,mntdcb ; enable operation of serial port
- mov al,0
- out dx,al
- mov modem.mdstat,mnst1b
- mov modem.mddat,mndatb
- mov modem.mdcom,mncmdb
- mov timer.tmdat,tmdatb
- mov timer.tmcmd,tmcmdb
- mov timer.tmsel,tmselb
- call domode
- call dobaud
- mov portinb,1 ; Remember port has been initialized.
- call clrbuf ; Clear input buffer.
- sti ; Allow interrupts
- pop es
- initb0: ret
- INITB ENDP
-
- ; Reset standard serial port
-
- RESETA PROC NEAR
- cmp portina,0 ; Did we reset port already?
- je rsta0 ; Yes, so just leave.
- push es
- cli ; Disable interrupts
- xor ax,ax ; Address low memory
- mov es,ax
- mov ax,oldsera ; Restore interrupt vector
- mov es:[4*icsvcta],ax
- mov ax,oldsega
- mov es:[4*icsvcta+2],ax
- mov dx,intmska ; restore old master controller mask
- mov al,oldmska
- out dx,al
- mov dx,mnmska ; disable serial interrupts at port
- mov al,txmsk+rxmsk+tbemsk
- out dx,al
- mov portina,0 ; Remember port has been reset
- sti ; Allow interrupts
- pop es
- rsta0: ret
- RESETA ENDP
-
- ; Reset optional (H14) serial port
-
- RESETB PROC NEAR
- cmp portinb,0 ; Did we reset port already?
- je rstb0 ; Yes, so just leave.
- push es
- cli ; Disable interrupts
- xor ax,ax ; Address low memory
- mov es,ax
- mov ax,oldserb ; Restore interrupt vector
- mov es:[4*icsvctb],ax
- mov ax,oldsegb
- mov es:[4*icsvctb+2],ax
- mov dx,intmskb ; restore old slave controller mask
- mov al,oldmskb
- out dx,al
- mov dx,mnmskb ; disable serial interrupts at port
- mov al,txmsk+rxmsk+tbemsk
- out dx,al
- mov portinb,0 ; Remember port has been reset
- sti ; Allow interrupts
- pop es
- rstb0: ret
- RESETB ENDP
-
-
- ; serial port interrupt routine. This is not accessible outside this
- ; module, handles serial port receiver interrupts.
-
- SERINT PROC NEAR
- push ds ; save these on remote stack
- push ax
- mov ax,seg datas ; get our own data segment
- mov ds,ax
- mov mnsp,sp ; save remote stack information
- mov mnsseg,ss
- mov sp,offset mnstk ; switch to local stack
- mov ss,ax
- push es ; and save remaining registers
- push bp
- push di
- push si
- push dx
- push cx
- push bx
- mov es,ax
- call mnproc ; process the interrupt
- mov al,icEOI
- cmp flags.comflg,1 ; If using standard port
- je intr1
- mov dx,intcmdb ; or H14 vectored to master
- cmp dx,intcmda
- je intr1 ; only signal End of Interrupt to master,
- out dx,al ; otherwise signal to both slave and master.
- intr1: mov dx,intcmda
- out dx,al
- pop bx ; restore registers from stack
- pop cx
- pop dx
- pop si
- pop di
- pop bp
- pop es
- mov ax,mnsseg ; switch back to remote stack
- mov ss,ax
- mov ax,mnsp
- mov sp,ax
- pop ax
- pop ds
- iret
-
- ; handler for serial input
-
- mnproc: cld
- mov di,srcpnt ; get buffer pointer
- mov dx,modem.mdstat ; is data available?
- in al,dx
- test al,rxrdy
- jz mnpro7
- mov dx,modem.mddat ; read data
- in al,dx
- or al,al
- jz mnpro7 ; Ignore nulls.
- cmp al,7FH ; Ignore rubouts, too.
- jz mnpro7
- mov ah,al
- and ah,7fH ; only consider low-order 7 bits for flow ctl.
- mov bp,portval
- cmp ds:[bp].floflg,0 ; Doing flow control?
- je mnpro4 ; Nope.
- mov bx,ds:[bp].flowc ; Flow control char (BH = XON, BL = XOFF).
- cmp ah,bl ; Is it an XOFF?
- jne mnpro3 ; Nope, go on.
- mov xofrcv,true ; Set the flag.
- jmp short mnpro7
- mnpro3: cmp ah,bh ; Get an XON?
- jne mnpro4 ; No, go on.
- mov xofrcv,false ; Clear our flag.
- jmp mnpro7
- mnpro4: stosb
- cmp di,offset source + bufsiz
- jb mnpro5 ; not past end...
- mov di,offset source ; wrap buffer around
- mnpro5: mov srcpnt,di ; update ptr
- inc count
- cmp ds:[bp].floflg,0 ; Doing flow control?
- je mnpro7 ; No, just leave.
- cmp xofsnt,true ; Have we sent an XOFF?
- je mnpro7 ; Yes.
- cmp count,mntrgh ; Past the high trigger point?
- jbe mnpro7 ; No, we're within our limit.
- mov ah,bl ; Get the XOFF.
- call outchr ; Send it.
- nop ; ignore failure.
- nop
- nop
- mov xofsnt,true ; Remember we sent it.
- mnpro7: ret
-
- SERINT ENDP
-
- ; Dumb terminal emulator. Anyone wishing to enhance it is encouraged
- ; to do so.
-
- TERM PROC NEAR
- push es
- test ourflgs,inited ; Have we been here before
- jnz term01 ; if so, skip this stuff
- or ourflgs,inited ; show we've been here
- test ourflgs,kbtrflg
- jnz term0
- mov bx,ax
- and [bx].flgs,not havtt ; If no table then reset flag
- term0: mov si,ax ; save argument block locally
- mov di,offset ourarg
- mov ax,ds
- mov es,ax
- mov cx,size termarg
- rep movsb
- mov al,trans.escchr ; Calculate scan code for cntrl-escape char
- add al,40H ; Uncontollify escape char
- mov ah,02H ; Control byte for escape scan code
- mov escscan,ax ; save it
- call domsg ; tell user how we're connecting.
- term01: test ourflgs,movcur ; Do we need to reset cursor position
- jz term1
- mov dx,offset cmd
- mov cx,savcur
- mov word ptr la,cx
- mov noc,0
- mov cmd,1 ; Bios move cursor call
- mov cl,crtcmd
- int bios
- and ourflgs, not movcur
- term1: call prtchr ; Serial port input processor
- jmp short term2 ; ...have a char
- nop
- jmp term4 ; no char, continue
- term2: and al,7FH ; only use ASCII in terminal mode
- push ax
- mov dl,al
- mov ah,conout
- int dos ; display char
- pop ax
- test ourarg.flgs,capt ; are we capturing output?
- jz term3
- push ax
- call ourarg.captr
- pop ax
- term3: test ourflgs,fprint ; are we echoing to printer?
- jz term4
- call lstchr
-
- term4: test ourflgs,kbtrflg
- jz term50
- call inscan
- jmp short term1
- nop
- cmp al,printkey ; All shifts of print key do special duty.
- jne term41
- cmp ah,0
- jne term40 ; but toggle printer only if unshifted print
- xor ourflgs,fprint ; go toggle printer
- term40: call inckbo ; increment kbout pointer
- jmp term1
- term41: cmp al,byte ptr escscan ; Is it current escape key
- jne term42
- test ah,02 ; with ctrl + anything ?
- jz term42
- call inckbo
- jmp short termx ; it's ctrl-escape key so just return
- term42: call trnout ; Returns rskp if char not sent.
- jmp short term1 ; Translation found and already sent.
- nop ; no translation so move char via DCONIO
- cmp ax,brkstp ; is it unredefined/unshifted break/stop key
- jnz term50 ; if not, just continue
- mov ax,ctrl_s ; get a ^S ready
- test ourflgs,tlnxof ; have we already sent a ^S ?
- jz term43 ; no, we can just set flag and send the ^S
- mov ax,ctrl_q ; yes, so now we need a ^Q
- term43: xor ourflgs,tlnxof ; change the flag in either case
- call sndhst ; send our ^S/ ^Q - IO.SYS 2.11 won't do it
- mov ah,dconio ; do a dummy read to clear IO.SYS flush flag
- mov dl,0FFH
- int dos
- jmp term1 ; and go back for more
- term50: mov ah,dconio ; Keyboard input processor
- mov dl,0FFH
- int dos ; check console
- jnz term51
- jmp term1 ; no char, continue .Too far for rel jmp.
- term51: cmp al,ourarg.escc ; is it the escape char?
- je termx ; allows use of unredef left arrow key to esc
- call sndhst ; no translation, just send it out
- ; Check if it is a function key that user has defined in MS-DOS
- mov es,dosseg
- mov bx,fifobas
- cmp es:byte ptr sfkeyflg[bx],0
- jnz term50 ; if so, go back to dconio for rest of chars
- jmp term1 ; and go back for more
- termx: pop es
- ret
-
-
- ; do appropriate translations on input key, and transmit
- ; if translation entry found it sends char(s) to sndhst and returns normally
- ; if no translation entry is found, returns rskp with unsent scan code in ax
- ; so that CONIN in IO.SYS can do its translation if neessary.
-
- trnout: test ourflgs,kbtrflg ; is there a translation table?
- jz trnou3
- mov cx,ourarg.klen ; get table length and origin
- mov di,ourarg.ktab
- push es
- mov bx,ds
- mov es,bx
- jcxz trnou3 ; Needed for case of table zero length
- repne scasw ; look for key
- jne trnou3 ; if not found, return rskp
- sub di,ourarg.ktab ; reset to offset of replacement
- sub di,2
- add di,ourarg.krpl
- mov si,[di]
- mov cl,[si] ; get length of replacement
- mov ch,0
- jcxz trnou3 ; if length is zero, send nothing
- inc si
- trnou1: lodsb ; get replacement character
- push si
- push cx
- call sndhst ; send it to port
- pop cx
- pop si
- loop trnou1 ; continue until translation complete
- trnou2: call inckbo ; increment kbout pointer
- pop es
- ret ; return after translating and sending
- trnou3: pop es
- jmp rskp ; plain characters return rskp
-
- ; get key-in scan code from fifo buffer in IO.SYS
- ; if gets a key-in, skip returns with scan code in ax
- ; returns normally if no key-in
-
- inscan: push es
- mov es,dosseg ; Address IO.SYS segment with es
- and ourflgs,not autorepflg ; Reset auto repeat flag
- mov bx,fifobas ; Offset of fifobas in IO.SYS (from LCLINI)
- insca1: mov al,es:[bx].kbout ; Get value of kbin pointer
- cmp al,es:[bx].kbin ; Compare value of kbout pointer
- jz insca2 ; If equal, no key-in yet so exit
- sub ah,ah
- add bx,ax ; Calculate address pointed to (-2)
- mov ax,es:2[bx] ; Get scan code pointed to by kbout.
- xchg ah,al ; Get control byte -> ah, data byte -> al.
- mov savscn,ax ; Save scan data in case key repeat needed.
- pop es
- jmp rskp
- insca2: mov bx,fifobas
- cmp byte ptr es:[bx].kbrepflg,0 ; Is it time to repeat last key-in
- jz inscax ; Nope so exit
- mov ax,savscn ; Get last key-in
- or ourflgs,autorepflg ; Show we are on auto repeat cycle
- pop es ; And make it look like new
- jmp rskp
- inscax: pop es
- ret
-
- ; increments kbout pointer (with reset to zero) and returns normally
- ; (on auto repeat cycles resets kbrepflg and returns )
-
- inckbo: push es
- mov es,dosseg
- mov bx,fifobas
- test ourflgs,autorepflg ; new key-in or autorepeat
- jnz inckb2
- mov cl,0 ; Update kbout pointer to fifo
- cli
- cmp byte ptr es:[bx].kbout,kbfifosiz-2 ; End of fifo buff ?
- je inckb1 ; Yes, so start back at beginning
- mov cl,es:[bx].kbout ; No, just update our place
- add cl,2
- inckb1: mov es:[bx].kbout,cl ; Write back new pointer value
- sti
- jmp short inckbx
- inckb2: mov byte ptr es:[bx].kbrepflg,0 ; Reset autorepeat flag in IO.SYS
- inckbx: pop es
- ret
-
- ; send character in AL to port, with possible local echo
-
- sndhst: push ax
- mov ah,al
- call outchr ; send char to port
- nop ; ...don't care if it fails
- nop
- nop
- pop ax
- test ourarg.flgs,lclecho ; doing local echo?
- jz sndhs2
- mov dl,al
- mov ah,conout
- int dos ; if so, display char
- sndhs2: ret
-
- ; send character to printer. The only special case is the tab, which must
- ; be expanded to spaces because MS-DOS doesn't.
-
- lstchr: cmp al,tab
- jne lstch2
- mov ax,lstpos ; current column position
- mov cx,8 ; # of spaces = 8 - (column % 8)
- div cl
- sub cl,ah
- add lstpos,cx ; update the column position
- mov al,' '
- lstch1: call lstch4 ; print all the spaces
- loop lstch1
- ret
- lstch2: cmp al,cr ; CR returns column count to zero
- jne lstch3
- mov lstpos,0
- lstch3: cmp al,' ' ; only printable characters are counted
- jb lstch4
- cmp al,del
- je lstch4
- inc lstpos
- lstch4: mov dl,al ; print the character in any case
- mov ah,lstout
- int dos
- ret
-
- TERM ENDP
-
- ; Set heath emulation on/off.
-
- VTS PROC NEAR
- mov dx,offset nyimsg
- jmp tmsg
- VTS ENDP
-
- ; Save the screen to a buffer and then append buffer to a disk file. [jrd]
- ; Default filename is Kermit.scn; actual file can be a device too. Filename
- ; is determined by mssset and is passed as pointer dmpname.
-
- VTSTAT PROC NEAR ; For Status display [jrd]
- ret ; no emulator status to display
- VTSTAT ENDP
-
- ; Save the screen to a buffer and then append buffer to a disk file. [jrd]
- ; Default filename is Kermit.scn; actual file can be a device too. Filename
- ; is determined by mssset and is passed as pointer dmpname.
-
- DUMPSCR PROC NEAR ; Dumps screen contents to a file. Just Beeps here
- call beep ; [jrd]
- ret
- DUMPSCR ENDP
-
-
- ; Position the cursor according to contents of DX:
- ; DH contains row, DL contains column. Returns normally.
-
- POSCUR PROC NEAR
- push ax ; save regs. [jrd]
- push cx
- push si
- cmp dh,25 ; out of range just assumes high value
- jb poscu1
- mov dh,24
- poscu1: cmp dl,80
- jb poscu2
- mov dl,79
- poscu2: add dx,2020H ; add offset for ADM cursor addressing
- mov cpseq+2,dh
- mov cpseq+3,dl
- mov si,offset cpseq ; print sequence (ESC=rc)
- mov cx,4
- posc1: lodsb
- mov dl,al
- mov ah,conout
- int dos
- loop posc1
- pop si
- pop cx ; [jrd]
- pop ax
- ret
- POSCUR ENDP
-
- ; Locate; homes cursor position and disables its display. Returns normally.
-
- LOCATE PROC NEAR
- mov dx,offset nocur ; Disable cursor
- call tmsg
- mov dx,0 ; Go to top left corner of screen.
- jmp poscur
- LOCATE ENDP
-
- ; Delete a character from the terminal. This works by printing
- ; backspaces and spaces. Returns normally.
-
- DODEL PROC NEAR
- mov dx,offset delstr ; Erase weird character.
- jmp tmsg
- DODEL ENDP
-
- ; Move the cursor to the left margin, then clear to end of line.
- ; Returns normally.
-
- CTLU PROC NEAR
- mov dx,offset clrlin ; this just goes to left margin...
- call tmsg
- jmp clearl ; now clear line
- CTLU ENDP
-
- ; Clear to the end of the current line. Returns normally.
-
- CLEARL PROC NEAR
- mov dx,offset ceolseq ; clear sequence
- jmp tmsg
- CLEARL ENDP
-
- ; This routine blanks the screen and homes the cursor. Returns normally.
-
- CMBLNK PROC NEAR
- mov dx,offset clrseq ; clear screen and home cursor sequence
- jmp tmsg
- CMBLNK ENDP
-
- ; write a line in inverse video at the bottom of the screen...
- ; the line is passed in dx, terminated by a $. Returns normally.
-
- PUTMOD PROC NEAR
- push dx ; preserve message
- mov dx,24*100H ; line 24
- call poscur
- mov dx,offset formdat.invseq ; put into inverse video
- call tmsg
- pop dx ; print the message
- call tmsg
- mov dx,offset formdat.nrmseq ; normal video
- jmp tmsg ; Jump to return
- PUTMOD ENDP
-
- ; clear the mode line written by putmod. Returns normally.
-
- CLRMOD PROC NEAR
- mov dx,24*100H
- call poscur
- mov dx,offset ceolseq
- jmp tmsg
- CLRMOD ENDP
-
- ; Put a help message in a box at the top of the screen.
- ; This one uses inverse video (or yellow if color)
- ; Pass the message in ax, terminated by a null. Returns normally.
-
- PUTHLP PROC NEAR
- cld
- mov dx,ax ; Prepare to pass message to 'getnoc'
- call getnoc ;
- mov rnoc,cx ; This is unformatted NOC in message
- mov cx,5 ; Calculate formatted area needed (in words)
- rol bx,cl ; BX is no of lf's.
- mov NOC,bx
- mov cx,2
- ror bx,cl
- add NOC,bx ; This is Lines X 40
- add NOC,80 ; Current line + one more
- mov cx,NOC
- mov si,dx ; Source of message given us
- mov di,attrptr ; Pointer to screen attrib area
- mov ax,formdat.bldcrt ; Need bold attribute
- rep stosw ; Cover attribute area needed
- mov ax,formdat.nrmcrt ; Rest of screen needs normal color
- mov cx,1000 ; Whole screen
- sub cx,NOC ; Attribute area left to cover
- rep stosw ; Do it
- mov cx,1000 ; Fill screen data area with null bytes
- mov di,dispptr ; Pointer to screen data area
- xor ax,ax ; This is source of null bytes
- rep stosw ; Prepare clean screen data area
- mov cx,rnoc ; No of unformatted data bytes
- mov di,dispptr ; Destination is screen data area
- pthlp0: push di ; Save start of current line
- pthlp1: lodsb ; Load data bytes 1-by-1
- cmp al,cr ; Is this one an eol?
- jz pthlp2 ; Yep - handle cr/lf's ourselves
- stosb ; No - move character
- loop pthlp1 ; And go back for next
- jmp short pthlp3 ; Finished moving chars, so exit.
- pthlp2: dec cx ; Account for cr and lf
- dec cx
- inc si ; Skip the lf
- pop di ; Get start of current line.
- add di,80 ; Adjust pointer to next line
- jmp short pthlp0 ; And go back for more
- pthlp3: pop di
- mov noc,2000 ; We are going to write over whole screen
- mov cmd,2 ; Get cursor position before writing
- mov dx,offset cmd
- mov cl,crtcmd
- int bios ; Get cursor call
- mov cx,word ptr la
- mov savcur,cx ; Store cursor position
- mov la,24 ; Prepare to roll down 24 lines
- mov ca,0
- mov cmd,3 ; Screen roll down command
- mov dx,offset cmd
- mov cl,crtcmd
- int bios ; Do it!
- mov la,0 ; Begin our msg on top line of screen
- mov cmd,1 ; String write command
- int bios ; Write it.
- mov dx,offset upcur
- call tmsg
- mov dx,offset upcur ; Put cursor up onto clean screen
- call tmsg
- or ourflgs,movcur ; Tell that we've moved the cursor
- ret
- PUTHLP ENDP
-
- ; Receives message pointer in DX, terminating character in CL
- ; Returns with message ptr in DX, NOC in CX, and number of lf's in BX.
-
- GETNOC PROC NEAR
- cld
- mov di,dx
- mov al,cl ; Move terminator to AL
- mov cx,2000 ; Longest acceptible message.
- repnz scasb ; Look for terminator
- jz gtnoc1
- xor cx,cx
- ret ; Error return
- gtnoc1: sub di,dx ; Calculate NOC
- mov cx,di ; Move it to counter
- dec cx ; Discount terminator
- push cx ; Save NOC
- mov di,dx
- mov al,lf
- xor bx,bx
- gtnoc2: repnz scasb ; Now count lf's
- jcxz gtnoc3 ; If the counter ran out
- inc bx
- jmp short gtnoc2
- gtnoc3: pop cx ; Recover NOC
- ret
- GETNOC ENDP
-
-
-
- ; Produce a short beep. Returns normally.
-
- BEEP PROC NEAR
- mov dl,bell
- mov ah,conout
- int dos
- ret
- BEEP ENDP
-
- ; Prints $-terminated message in dx, for local use only
-
- TMSG PROC NEAR
- mov ah,prstr
- int dos
- ret
- TMSG ENDP
-
- ; Jumping to this location is like retskp. It assumes the instruction
- ; after the call is a jmp addr.
-
- RSKP PROC NEAR
- pop bp
- add bp,3
- push bp
- ret
- RSKP ENDP
-
- ; Jumping here is the same as a ret.
-
- R PROC NEAR
- ret
- R ENDP
-
- code ends
- end
-
- ; END OF MSXAPC.ASM
-